use actix_web::{ get, post, web, HttpResponse, Responder };
use rusqlite:: Connection;
use serde::{Deserialize, Serialize};

use crate::api::log;

#[derive(Debug, Serialize, Deserialize)]
struct Student {
    name: String,
    room: i16,
    point: f32
}

#[post("/api/student/add")]
pub async fn add_student(form_data: web::Form<Student>) -> impl Responder {

    println!("{:?}", form_data);

    let student = Student {
        name: form_data.name.clone(),
        room: form_data.room,
        point: form_data.point
    };

    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/add -> 数据库连接失败！");

    conn.execute(
        "INSERT INTO student (name, room, point) VALUES (?1, ?2, ?3)", 
        (&student.name, &student.room, &student.point)
    ).expect("student.rs /api/student/add -> 插入数据失败！");

    let _ = log::write_log(&format!("添加学生：{}", student.name), "新建学生信息！");

    HttpResponse::Ok().body("add new student success!")
}

#[post("/api/student/delete")]
pub async fn delete_student(req_body: String) -> impl Responder {
    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/delete -> 数据库连接失败！");

    conn.execute(
        "DELETE FROM student WHERE name = ?1",
        (&req_body,)
    ).expect("student.rs /api/student/delete -> 删除数据失败！");

    let _ = log::write_log(&format!("删除学生：{}", &req_body), "移除学生信息！");

    HttpResponse::Ok().body("delete student success!")
}

#[derive(Debug, Serialize, Deserialize)]
struct StudentEdit {
    original_name: String,
    edit_name: String,
    room: i16,
    point: f32
}

#[post("/api/student/edit")]
pub async fn edit_student(form_data: web::Form<StudentEdit>) -> impl Responder {
    
    let s = StudentEdit {
        original_name: form_data.original_name.clone(),
        edit_name: form_data.edit_name.clone(),
        room: form_data.room,
        point: form_data.point
    };

    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/edit -> 数据库连接失败！");
    conn.execute(
        "UPDATE student SET name = ?1, room = ?2, point = ?3 WHERE name = ?4",
        (&s.edit_name, &s.room, &s.point, &s.original_name)
    ).expect("student.rs /api/student/edit -> 更新数据失败！");


    let _ = log::write_log(&format!("编辑学生：{}, 修改名称为：{}, 修改宿舍为：{}, 修改分数为：{}", &s.original_name, &s.edit_name, &s.room, &s.point), &format!("编辑学生：{} 的信息！", &s.original_name));
    HttpResponse::Ok().body("edit student success!")
}

#[get("/api/student/read")]
pub async fn read_student() -> impl Responder {

    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/read -> 数据库连接失败！");
    let mut stmt = conn.prepare("SELECT name, room, point FROM student").expect("student.rs /api/student/read -> 查询失败！");
    
    let student_iter = stmt.query_map([], |row| {
        Ok(Student {
            name: row.get(0)?,
            room: row.get(1)?,
            point: row.get(2)?
        })
    }).expect("log.rs /api/student/read -> student_iter 迭代失败！");

    let mut students = Vec::new();
    for s in student_iter {
        students.push(s.unwrap());
    }

    HttpResponse::Ok().json(serde_json::to_string(&students).unwrap())
}

#[derive(Debug, Serialize, Deserialize)]
struct Room {
    #[allow(dead_code)]
    room: i16
}

#[get("/api/student/room_list")]
pub async fn read_room_list() -> impl Responder {
    
    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/room_list -> 数据库连接失败！");
    let mut stmt = conn.prepare("SELECT DISTINCT room FROM student").expect("student.rs /api/student/room_list -> 查询失败！");

    let room_iter = stmt.query_map([], |row| {
        Ok(Room {
            room: row.get(0)?
        })
    }).expect("student.rs /api/student/room_list -> room_iter 迭代失败！");

    let mut rooms = Vec::new();
    for r in room_iter {
        rooms.push(r.unwrap());
    }

    HttpResponse::Ok().json(serde_json::to_string(&rooms).unwrap())
}

#[get("/api/student/find_room/{room}")]
pub async fn find_room(path: web::Path<i16>) -> impl Responder {
    let room = path.into_inner();
    let sql = format!("SELECT * FROM student WHERE room = {}", room);
    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/find_room -> 数据库连接失败！");
    let mut stmt = conn.prepare(sql.as_str()).expect("student.rs /api/student/find_room -> 查询失败！");

    let room_iter = stmt.query_map([], |row| {
        Ok(Student {
            name: row.get(0)?,
            room: row.get(1)?,
            point: row.get(2)?
        })
    }).expect("student.rs /api/student/find_room -> room_iter 迭代失败！");

    let mut students = Vec::new();
    for s in room_iter {
        students.push(s.unwrap());
    }

    // println!("{:?}", students);

    HttpResponse::Ok().json(serde_json::to_string(&students).unwrap())
}

#[derive(Debug, Serialize, Deserialize)]
struct ImportStudent {
    list: String,
    point: f32
}

#[post("/api/student/import")]
pub async fn import_student(form_data: web::Form<ImportStudent>) -> impl Responder {
    let imp_student = ImportStudent {
        list: form_data.list.clone(),
        point: form_data.point
    };

    let names: Vec<String> = imp_student.list.split("\r\n").map(|s| s.to_string()).collect();

    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/import -> 数据库连接失败！");
    for name in names {
        conn.execute(
            "INSERT INTO student (name, room, point) VALUES (?1, ?2, ?3)", 
            (name, 0, imp_student.point)
        ).expect("student.rs /api/student/import -> 插入数据失败！");
    }

    let _ = log::write_log(&format!("批量导入了一堆学生..."), "新建学生信息！");

    HttpResponse::Ok().body("import student success!")
}


// 

#[derive(Debug, Serialize, Deserialize)]
struct StudentPoint {
    name: String,
    point: f32,
    describe: String
}

#[post("/api/student/add_point")]
pub async fn add_point(form_data: web::Form<StudentPoint>) -> impl Responder {
    let s = StudentPoint {
        name: form_data.name.clone(),
        point: form_data.point,
        describe: form_data.describe.clone(),
    };

    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/add_point -> 数据库连接失败！");
    conn.execute(
        "UPDATE student SET point = point + ?1 WHERE name = ?2", 
        (s.point, &s.name)
    ).expect("student.rs /api/student/add_point -> 更新数据失败！");

    let _ = log::write_log(&format!("学生 {} 加了 {} 分", s.name, s.point), s.describe.as_str());

    HttpResponse::Ok().body("add point success!")
}

#[post("/api/student/deduct_point")]
pub async fn deduct_point(form_data: web::Form<StudentPoint>) -> impl Responder {
    let s = StudentPoint {
        name: form_data.name.clone(),
        point: form_data.point,
        describe: form_data.describe.clone(),
    };

    let conn = Connection::open("./data/data.db").expect("student.rs /api/student/add_point -> 数据库连接失败！");
    conn.execute(
        "UPDATE student SET point = point - ?1 WHERE name = ?2", 
        (s.point, &s.name)
    ).expect("student.rs /api/student/add_point -> 更新数据失败！");

    let _ = log::write_log(&format!("学生 {} 扣了 {} 分", s.name, s.point), s.describe.as_str());

    HttpResponse::Ok().body("deduct point success!")
}